package db_main

import (
	"errors"
	"fmt"
	global2 "longmen/server/config/global"
	_const "longmen/server/pkg/common/helper/const"
	utils2 "longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/db/mysql"
	"longmen/server/pkg/db/mysql/models/models_main"
	"strings"

	"longmen/server/pkg/common/api_models"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

//func GetUserParam(param map[string]interface{}) (*models_main.User, error) {
//	fName := "GetUserParam"
//	o := &models_main.User{}
//	table := o.TableName()
//	t := global2.GetX().Table(table)
//	models.Condition(t, param, "", "", 0, 0)
//	err := t.Order("id desc").Limit(1).Find(o).Error
//	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
//		err = nil
//	} else if err != nil {
//		err = fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
//	}
//	return o, err
//}

func GetUserAccountByMobile(mobile string) (string, error) {
	fName := "GetUserParam"

	// 驗證手機號存在
	exists, err := global2.BloomExists(global2.BLOOM_MOBILE, mobile)
	if err != nil {
		global2.Log.Errorf("Login varify bloom error : %s", err.Error())
	}
	if !exists {
		return "", fmt.Errorf("该手机号尚未注册")
	}

	o, err := mysql.GetUserParam(map[string]interface{}{"mobile": mobile})
	if errors.Is(err, gorm.ErrRecordNotFound) {
		err = nil
	}
	if err != nil {
		err = fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}
	return o.Account, err
}

func GetUserByMobile(mobile string) (*models_main.User, error) {
	fName := "GetUserParam"

	// 驗證手機號存在
	exists, err := global2.BloomExists(global2.BLOOM_MOBILE, mobile)
	if err != nil {
		global2.Log.Errorf("Login varify bloom error : %s", err.Error())
	}
	if !exists {
		return nil, fmt.Errorf("该手机号尚未注册")
	}

	o, err := mysql.GetUserParam(map[string]interface{}{"mobile": mobile})
	if errors.Is(err, gorm.ErrRecordNotFound) {
		err = nil
	}
	if err != nil {
		err = fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}
	return o, err
}

func GetUserAccountByName(username string) (*models_main.User, error) {
	fName := "GetUserParam"
	var user models_main.User
	table := mysql.GetRTable(&models_main.User{})
	err := table.Where("account=?", username).Find(&user).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		err = nil
	}
	if err != nil {
		err = fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
		return nil, err
	}
	return &user, nil
}
func GetUsersParam(param map[string]interface{}, order string, page, size int) ([]*models_main.User, error) {
	fName := "GetUsersParam"
	o := make([]*models_main.User, 0)
	table := mysql.GetRTable(&models_main.User{})
	mysql.Condition(table, param, "", order, page, size)
	err := table.Find(&o).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		err = nil
	}
	if err != nil {
		err = fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}
	return o, err
}

func GetAnchors(param map[string]interface{}, order string, checkSubUID int, page, size int) ([]*api_models.User, error) {
	fName := "GetAnchors"
	o := make([]*api_models.User, 0)
	table := mysql.GetRTable(&models_main.User{})
	mysql.Condition(table, param, "", order, page, size)
	err := table.Find(&o).Error
	if err != nil {
		err = fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}
	return o, err
}

func GetUserCount(param map[string]interface{}) (int64, error) {
	var o int64
	err := mysql.Condition(mysql.GetRTable(&models_main.User{}), param, "", "", 0, 0).Count(&o).Error
	if err != nil {
		err = fmt.Errorf("%s%s", utils2.Convert2(), err.Error())
	}
	return o, err
}

func CheckNicknameReview(userID int) (int64, error) {
	var o int64
	table := mysql.GetRTable(&models_main.UserApply{}).Where("user_id=? and change_type=0 and status=0", userID)
	err := table.Count(&o).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		err = nil
	}
	if err != nil {
		err = fmt.Errorf("%s%s", utils2.Convert2(), err.Error())
	}
	return o, err
}

func UpdateUser(columns []string, user *models_main.User) error {
	err := global2.GetX().
		Select(columns).
		Save(user).
		Error
	if err != nil {
		return fmt.Errorf("%s%s", utils2.Convert2(), err.Error())
	}
	return nil
}

func IncreaseUser(session *gorm.DB, incNum int, incCol string, whereNum int, whereCol string) error {
	fName := "IncreaseUser"
	if session == nil {
		session = global2.GetX()
	}
	err := session.Exec(fmt.Sprintf("UPDATE %s SET %s = %s + %d WHERE %s = ?", (&models_main.User{}).TableName(), incCol, incCol, incNum, whereCol), whereNum).Error
	if err != nil {
		session.Rollback()
		return fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}
	return nil
}

func UpdateUserByTransactions(session *gorm.DB, columns []string, user *models_main.User) error {
	err := session.Select(columns).Updates(user).Error
	for _, column := range columns {
		if strings.EqualFold(column, "avatar") {
			session.Exec("update db.db_live set anchor_avatar=? where anchorid=?", user.Avatar, user.Id)
			break
		}
	}
	if err != nil {
		session.Rollback()
		return fmt.Errorf("%s%s", utils2.Convert2(), err.Error())
	}
	return nil
}
func InsertInviteByTx(tx *gorm.DB, ir *models_main.InviteRecord) error {
	err := tx.Create(ir).Error
	if err != nil {
		tx.Rollback()
		return fmt.Errorf("%s%s", utils2.Convert2(), err.Error())
	}
	return nil
}
func GetInvite(uid int) ([]*models_main.InviteRecord, error) {
	var o []*models_main.InviteRecord
	err := mysql.GetRTable(&models_main.InviteRecord{}).Where("uid = ?", uid).Find(&o).Error
	if err != nil {
		return nil, fmt.Errorf("%s%s", utils2.Convert2(), err.Error())
	}
	return o, nil
}
func InsertUserApply(session *gorm.DB, userApply *models_main.UserApply) error {
	fName := "InsertUserApply"
	err := session.Create(userApply).Error
	if err != nil {
		session.Rollback()
		return fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}
	return nil
}

func InsertUserByTransactions(tx *gorm.DB, user *models_main.User) error {
	if err := tx.Create(user).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("%s%s", utils2.Convert2(), err.Error())
	}
	return nil
}

func GetPartUsersParam(param map[string]interface{}, order string, page, size int) ([]*models_main.PartUser, error) {
	fName := "GetPartUsersParam"
	o := make([]*models_main.PartUser, 0)
	table := mysql.GetRTable(&models_main.PartUser{})
	mysql.Condition(table, param, "", order, page, size)
	err := table.Find(&o).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		err = nil
	}
	if err != nil {
		err = fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}
	return o, err
}

func GetUserForUpdate(session *gorm.DB, uid int) (*models_main.User, error) {
	fName := "GetUserForUpdate"
	o := &models_main.User{}
	err := session.Clauses(clause.Locking{Strength: "UPDATE"}).Find(o, uid).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		err = nil
	}
	if err != nil {
		session.Rollback()
		err = fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}
	return o, err
}

func VerifyToken(token string, uid int, platform int) (bool, error) {
	fName := "VerifyToken"
	var count int64
	if platform > 0 {
		if err := global2.GetX().Model(&models_main.User{}).Where("id = ? and token = ?", uid, token).Count(&count).Error; err != nil {
			return false, fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
		}
	} else {
		if err := global2.GetX().Model(&models_main.User{}).Where("id = ? and token_web = ?", uid, token).Count(&count).Error; err != nil {
			return false, fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
		}
	}

	if count > 0 {
		return true, nil
	}
	return false, nil
}

func GetUserAsset(user *models_main.User) (*api_models.UserAsset, error) {
	fName := "GetUserAsset"

	userAsset := new(api_models.UserAsset)

	userAsset.Diamond = user.Diamond
	userAsset.ProfitDiamond = user.ProfitDiamond

	// 累计提现
	err := mysql.GetRTable(&models_main.UserWithdraw{}).Select("sum(apply_amount) as total_withdraw").Where("uid=? and status=2", user.Id).
		Order("id asc").
		Limit(1).
		Find(&userAsset).Error
	if err != nil {
		return nil, fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}

	userAsset.IssetPassword = 1
	userAsset.IsAnchor = user.IsAnchor
	//if user.PendingStatus == 0 && user.PendingNickName != "" {
	//	userAsset.IsUnderReviewNickname = 1
	//}
	if user.PayPassword != "" {
		userAsset.IssetPayPassword = 1
	}

	var cards int64
	err = mysql.GetRTable(&models_main.UserBank{}).Where("uid=? and deleted=0", user.Id).Count(&cards).Error

	if cards > 0 {
		userAsset.IsbindBankCard = 1
	}

	if err != nil {
		return nil, fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}

	return userAsset, nil
}

func InsertUserPromoteByTx(tx *gorm.DB, userPromote *models_main.UserPromote) error {
	err := tx.Create(userPromote).Error
	if err != nil {
		tx.Rollback()
		return fmt.Errorf("%s%s", utils2.Convert2(), err.Error())
	}
	return nil
}

func GetInvitedUser(uid uint) ([]*api_models.InvitedUser, error) {
	userPromoteList := make([]*api_models.InvitedUser, 0)
	err := global2.GetR().
		Raw(" SELECT u.avatar AS avatar ,"+
			" u.nick_name AS nick_name FROM db_user_promote up LEFT JOIN db_user u ON up.uid = u.id "+
			" WHERE  up.referer_id= ? ORDER BY up.created_time DESC ", uid).
		Find(&userPromoteList).Error
	if err != nil {
		return nil, fmt.Errorf("%s%s", utils2.Convert2(), err.Error())
	}
	return userPromoteList, nil
}

/*
*
检查用户有没有足够的钱来扣，如果不够就返回用户的余额
返回false, 98, nil 表示用户钱不够，只剩98
*/
func UserHasEnoughMoney(uid uint, amount uint, coinType int) (bool, uint, error) {
	fName := "UserHasEnoughMoney"
	o := &models_main.User{}
	table := o.TableName()
	t := global2.GetX().Table(table)
	mysql.Condition(t, map[string]interface{}{"id": uid}, "", "", 0, 0)
	err := t.Find(o).Error
	if err != nil {
		err = fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}
	iBalance := uint(o.Gold)
	if coinType == int(_const.CoinDiamond) {
		iBalance = uint(o.Diamond)
	}
	if iBalance < amount { //不够钱扣
		return false, iBalance, nil
	}
	return true, amount, nil
}

func CountAcc(account string) int64 {
	var quantity int64
	global2.GetR().Raw("select 1 from db_user where account=?", account).Count(&quantity)
	return quantity
}

func GetPartUserParam(param map[string]interface{}) (*models_main.PartUser, error) {
	fName := "GetPartUserParam"
	o := &models_main.PartUser{}
	table := o.TableName()
	t := global2.GetX().Table(table)
	mysql.Condition(t, param, "", "", 0, 0)
	err := t.Order("id desc").Limit(1).Find(o).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		err = nil
	} else if err != nil {
		err = fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}
	return o, err
}

func GetAllUserIds() ([]int64, error) {
	userIds := make([]int64, 0)
	return userIds, global2.GetX().Model(&models_main.User{}).Select("id").Pluck("id", &userIds).Error
}

func GetAll6tBindUsers() ([]*models_main.DbUserBinding6taccount, error) {
	users := make([]*models_main.DbUserBinding6taccount, 0)
	return users, global2.GetX().Model(&models_main.DbUserBinding6taccount{}).Select("uid,account").Find(&users).Error
}
